package exercise;

import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.FutureTask;
import java.util.concurrent.atomic.AtomicInteger;

public class Exercise008 {
    public static void main(String[] args) throws Exception {
        // test01();
        // test02();
        // test03();
        // test04();
        test05();
    }

    public static void test01(){
        // 有三个线程，分别只能打印A，B和C
        // 要求按顺序打印ABC，打印10次
        final Object locker = new Object();

        Thread t1 = new Thread(()->{
            for(int i = 0;i<10;i++){
                synchronized(locker){
                    while(state != 1){
                        try {
                            locker.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print("A");
                    state = 2;
                    locker.notifyAll();
                }
            }
        });
        Thread t2 = new Thread(()->{
            for(int i = 0;i<10;i++){
                synchronized(locker){
                    while(state != 2){
                        try {
                            locker.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print("B");
                    state = 3;
                    locker.notifyAll();
                }
            }
        });
        Thread t3 = new Thread(()->{
            for(int i = 0;i<10;i++){
                synchronized(locker){
                    while(state != 3){
                        try {
                            locker.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println("C");
                    state = 1;
                    locker.notifyAll();
                }
            }
        });
        t1.start();
        t2.start();
        t3.start();
        try{
            t1.join();
            t2.join();
            t3.join();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    private static int state = 3;
    public static void test02(){
        // 有三个线程，线程名称分别为：a，b，c。
        // 需要让他们同时启动，并按 c，b，a的顺序打印
        final Object locker = new Object();

        Thread a = new Thread(()->{
            synchronized(locker){
                while(state != 1){
                    try {
                        locker.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName());
            }
        },"a");
        Thread b = new Thread(()->{
            synchronized(locker){
                while(state != 2){
                    try {
                        locker.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(Thread.currentThread().getName());
                state = 1;
                locker.notifyAll();
            }
        },"b");
        Thread c = new Thread(()->{
            synchronized(locker){
                while(state != 3){
                    try {
                        locker.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.print(Thread.currentThread().getName());
                state = 2;
                locker.notifyAll();
            }
        },"c");
        a.start();
        b.start();
        c.start();
        try{
            a.join();
            b.join();
            c.join();
        }catch(InterruptedException e){
            e.printStackTrace();
        }
    }
    // 基于 Callable 实现 1+2+3+...+1000
    public static void test3() throws Exception{
        Callable<Integer> callable = new Callable<Integer>(){
            @Override
            public Integer call() throws Exception {
                int sum = 0;
                for (int i = 1; i <= 1000; i++) {
                    sum += i;
                }
                return sum;
            }
        };
        
        FutureTask<Integer> futureTask = new FutureTask<Integer>(callable); 
        Thread t = new Thread(futureTask);
        t.start();

        Integer result = futureTask.get();
        System.out.println("1+2+3+...+1000 = " + result);
    }
    // 基于 AtomicInteger 实现多线程自增同一个变量
    public static void test4(){
        AtomicInteger atomicInteger = new AtomicInteger(0);
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                atomicInteger.incrementAndGet();
            }).start();
        }
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(atomicInteger);
    }
    // 基于 CountDownLatch 模拟跑步比赛的过程
    public static void test05(){
        CountDownLatch countDownLatch = new CountDownLatch(10);
        System.out.println("比赛开始");
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                System.out.println(Thread.currentThread().getName() + " 开始跑步");
                try {
                    Thread.sleep((long) (Math.random() * 10000));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + " 跑步结束");
                countDownLatch.countDown();
            }).start();
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("比赛结束");
    }
}
